// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright © 2018-2019 Ariadne Devos

/* (Extracted and transcluded from <sHT/nospec.h> */

/* (Translated from the x86 implementation; "sbb" has been
  translated to "sbc". Apparently Linux does the same.)

  The operand order has been found by brute force.

  Linux does "sbc %0, zrx, zrx

  One would expect "sbc %0, %0, %0" to let the test pass,
  being %0 <- %0 - %0 - !carry, but it doesn't somehow.
  Instead, reuse %1 or %2 (length, pos), as Linux does.

  Alternatively, one could do "sbc %0, %0, #0" and before
  that, set %0 to 0, but that's one instruction longer.

  TODO: Linux uses xzr as last two registers on arm64,
  perhaps do the same. */
#define _sHT_index_mask(maskp, pos, length) \
	__asm__("cmp %2, %1\n\tsbc %0, %1, %1" : "=&r" (*(maskp)) : "r" ((length)), "rI" ((pos)) : "cc")

/* TODO XXX FIXME: use csdb, isb or some mcr.
  The specific instruction depends on the CPU model and
  Thumb/ARM state.

  I do not have a real ARM system setup for testing yet,
  so do this later (patches welcome).

  Some implementation hints are in the git history. */
/* volatile "memory" is for paranoia, to avoid reordering. */
#define _sHT_speculation_barrier() \
		__asm__ volatile("" : : : "memory")
